using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.MediaCenter.Hosting;
using Microsoft.MediaCenter.ListMaker;
using System.Threading;
using Microsoft.MediaCenter.UI;
using Level65.WMVHelper;
using Level65.ClipShow;

namespace ClipShow
{
    public class ExeClass : IAddInModule, IAddInEntryPoint
    {
        //
        // Initialize (IAddInModule)
        //

        public void Initialize(Dictionary<string, object> appInfo, Dictionary<string, object> entryPointInfo)
        {

        }

        //
        // Uninitialize (IAddInModule)
        //

        public void Uninitialize()
        {
        }


        //
        // Launch (IAddInModule)
        //

        public void Launch(AddInHost host)
        {
            s_session = new HistoryOrientedPageSession();
            s_session.GoToPage("resx://ClipShow/ClipShow.Resources/MediaBrowse");
        }

        private static HistoryOrientedPageSession s_session;

    }

    public class CLibBuilder : IAddInModule, Microsoft.MediaCenter.ListMaker.IListMakerApp
    {
        public CLibBuilder()
        {
        }

        public void Initialize(Dictionary<string, object> appInfo, Dictionary<string, object> entryPointInfo)
        {
            // ToDo: Called when PlugIn is initalized - can be used for very quick Initializations
            return;
        }

        public void Uninitialize()
        {
            // ToDo: Called when PlugIn is unloaded - can be used to dispose all memory
            return;
        }

        #region IListMakerApp Members

        long _byteCap = 700 * 1024 * 1024;      // ToDo: Calculate real Byte Capacity if necessary
        long _byteUsed = 0;
        TimeSpan _timeCap = new TimeSpan(3, 0, 0);    // ToDo: Calculate real Time Capacity if necessary
        TimeSpan _timeUsed = new TimeSpan(0, 0, 0);
        int _itemCap = 15;                  // ToDo: Calculate real Item Capacity if necessary
        int _itemUsed = 0;
        float _progressPercentage = 0.0F;
        TimeSpan _timeRemaining = TimeSpan.Zero;
        ListMakerList _lml = null;
        private Thread _thread;
        bool _fCancel = false;

        public string PageTitle     // Return string used for the status overlay during ListMaker. eg: "Burn CD"
        {
            get
            {
                return "Create clipShow playlist";        // Return null for default
            }
        }

        public Uri MainIcon      // Return path to the Main background icon used during ListMaker
        {
            get
            {
                return null;        // Return null for default
            }
        }

        public Uri StatusBarIcon // Return path to the icon used on the status bar
        {
            get
            {
                return null;        // Return null for default
            }
        }

        public Uri ViewListIcon  // Return path to the icon used for the View/Edit page
        {
            get
            {
                return null;        // Return null for default
            }
        }

        public string ViewListButtonTitle   // Return string used for the "View List" button. eg: "View CD"
        {
            get
            {
                return "View playlist";        // Return null for default
            }
        }

        public string SaveListButtonTitle  // Return string used for the "Save List button. eg: "Burn CD"
        {
            get
            {
                return "Save playlist";        // Return null for default
            }
        }

        public string ViewListPageTitle  // Return string used for the title of the View/Edit page. eg: "View CD"
        {
            get
            {
                return "View playlist";        // Return null for default
            }
        }

        public string CreatePageTitle   // Return string used for the title of the initial ListMaker screen. eg: "Name CD"
        {
            get
            {
                return "clipShow playlist setup";        // Return null for default
            }
        }

        public virtual long ByteUsed
        {
            get
            {
                return _byteUsed;
            }
        }

        public virtual float PercentComplete
        {
            get
            {
                return _progressPercentage;
            }
        }

        public virtual int ItemUsed
        {
            get
            {
                return _itemUsed;
            }
        }

        public virtual void Repeat(ListMakerList list)
        {
            // ToDo: called when user request reprocessing of the list after completion - frequently the same as Launch()
            Launch(list);
        }

        public virtual bool Repeatable
        {
            get {
                // ToDo: Whether or not the user is allowed to repeat this post-completion
                return false;
            }
        }

        public virtual bool ShowCapacityAsPercentage
        {
            get { return false;}
        }

        public virtual TimeSpan TimeUsed
        {
            get {return _timeUsed;}
        }

        public virtual bool CanProceed
        {
            get
            {
                // ToDo: Called on user selection of the PlugIn to indicate whether or not we are in a state to proceed. 
                //	 eg: Is there a blank Disc in the drive
                _fCancel = false;       //Reset this in case it got cleared somewhere else
                return true;
            }
        }

        public bool IsPercentCompleteKnown
        {
            get { return true;}
        }

        public bool IsTimeRemainingKnown
        {
            get {return false;}
        }

        public virtual TimeSpan TimeRemaining
        {
            get {return _timeRemaining;}
        }

        public virtual void RemoveAllItems()
        {
            _byteUsed = 0;
            _timeUsed = TimeSpan.Zero;
            _itemUsed = 0;
        }

        public virtual void Launch(ListMakerList list)
        {
            _progressPercentage = 0.0F;
            _timeRemaining = new TimeSpan(0, 0, 20);      // ToDo: Calculate true time remaining
            _lml = list;

            _wmvReader.ReaderAlert += new ReaderEventHandler(wmvReader_ReaderAlert);
            
            // List Processing should happen on a background thread and this thread should return immediately
            _thread = new Thread(new ThreadStart(ProcessList));
            _thread.Name = "ProcessListThread";
            _thread.IsBackground = true;        // In the event of an emergency, or abnormal shutdown, don't hang.
            _thread.Priority = ThreadPriority.Normal;
            _thread.Start();
        }

        void wmvReader_ReaderAlert(object sender, ReaderEventArgs e)
        {
            _itemCtr++;
            _progressPercentage = ((float)_itemCtr) / _count;
            OnProgressUpdate(null, null);
        }

        public event EventHandler ProgressChanged;
        public event EventHandler Completed;
        int _count = 0;
        int _itemCtr = 0;

        private void GetTrueCount(ListMakerList source)
        {
            foreach (ListMakerItem lmi in source)
            {
                if (null != lmi)
                {
                    if (lmi.MediaTypes == MediaTypes.Folder)
                    {
                        GetTrueCount(lmi.Children);
                    }
                    else
                    {
                        _count++;
                    }
                }
            }
        }
        private void ProcessList()
        {
            OnProgressUpdate(null, null);
            GetTrueCount(_lml);

            // Count for second pass of thumbnail creation
            //_count = _count * 2;

            foreach (ListMakerItem lmi in _lml)
            {
                WriteItem(lmi);
                _itemCtr++;
                _progressPercentage = ((float)_itemCtr) / _count;
                OnProgressUpdate(null, null);
            }

            // First build the playlist
            ClipCollection col = new ClipCollection();
            col.Name = _lml.ListTitle;

            ClipItem ci = new ClipItem();
            ci.Keywords = "ALL";
            ci.Name = _lml.ListTitle;

            Random r = new Random(unchecked((int)DateTime.Now.Ticks));
            int mediaItem = r.Next(0, _result.Count);

            MediaMetaData tempMd = (MediaMetaData)_result[mediaItem];
            ci.ThumbnailUrl = tempMd.ThumbnailUrl;
            ci.Count = _result.Count;

            ci.MediaItems.AddRange(_result);
            col.Items.Add(ci);
            _wmvReader.PersistThumbnailWork();

            Storage st = new Storage();
            st.PersistChannel(col, false);

            // Now add items to media library 
            ClipShowContent cm = new ClipShowContent();
            cm.ContentSourceName = _lml.ListTitle;
            cm.MediaItems.AddRange(_result);
            cm.WatchFolders = true;

            // Now Build the accompanying channels
            Topics myTopics = new Topics();
            ArrayList channelTopics = myTopics.BuildTopics(cm);
            int maxTopics = channelTopics.Count - Convert.ToInt32((channelTopics.Count * 0.15));

            ClipItem defaultCI = new ClipItem();
            defaultCI.Count = _result.Count;
            defaultCI.Keywords = "ALL";
            defaultCI.Name = "All Media";
            MediaMetaData wmd = (MediaMetaData)cm.MediaItems[0];
            defaultCI.ThumbnailUrl = wmd.ThumbnailUrl;
            cm.KeywordItems.Add(defaultCI);

            int Ctr = channelTopics.Count;
            foreach (ClipTopic ciTopic in channelTopics)
            {
                cm.KeywordItems.Add(BuildChannel(ciTopic.Topic,
                    ciTopic.Keywords,
                    ciTopic.MediaCount, ciTopic.ThumbnailSample));

                // Bail when we get under our max topics
                if (Ctr < (channelTopics.Count - maxTopics))
                {
                    break;
                }
                Ctr--;
            }
            st.PersistMediaLibrary(cm);

            OnCompletionEvent(null, null);
        }

        private static ClipItem BuildChannel(string channelName, string keywords, long videoCount, string thumbNail)
        {
            ClipItem ci = new ClipItem();
            ci.Name = channelName;
            ci.Keywords = keywords;
            ci.Count = videoCount;
            ci.ThumbnailUrl = thumbNail;

            return (ci);
        }
        void OnProgressUpdate(object source, EventArgs e)
        {
            if (_progressPercentage <= 1.0F && !_fCancel)
            {
                if (ProgressChanged != null)
                    ProgressChanged(null, null);
            }
        }

        void OnCompletionEvent(object source, EventArgs e)
        {
            if (Completed != null)
                Completed(null, null);
        }

        private Reader _wmvReader = new Reader();
        private ArrayList _result = new ArrayList();
        private void WriteItem(ListMakerItem lmi)
        {
            if (lmi.MediaTypes == Microsoft.MediaCenter.ListMaker.MediaTypes.Folder)
            {
                // Recurse into Folders
                ListMakerList lml = lmi.Children;
                foreach (ListMakerItem lmiT in lml)
                {
                    WriteItem(lmiT);
                }
            }
            else
            {
                _result.Add(_wmvReader.ReadMetaData(lmi.FileName));
            }
        }

        public virtual CapacityFormat CapacityFormat
        {
            get { return CapacityFormat.Byte; }       //Data or HighMat
        }

        public virtual void ItemRemoved(ListMakerItem item)
        {
            _byteUsed -= item.ByteSize;
            _timeUsed -= item.Duration;
            _itemUsed--;
        }

        public virtual int ItemCapacity
        {
            get { return _itemCap;}
        }

        public virtual bool ShowRemainingCapacity
        {
            get
            {
                // ToDo: Return preferred status format. ie. Counting up or down
                return false;
            }
        }

        public virtual bool IsOrderImportant
        {
            get
            {
                // ToDo: Return whether or not the user can sort items on the Edit List page
                return false;
            }
        }

        public virtual Microsoft.MediaCenter.ListMaker.MediaTypes SupportedMediaTypes
        {
            get
            {
                // ToDo: Return Union of supported media types for this PlugIn
                return Microsoft.MediaCenter.ListMaker.MediaTypes.RecordedTV |
                        Microsoft.MediaCenter.ListMaker.MediaTypes.Videos;
                //return Microsoft.MediaCenter.ListMaker.MediaTypes.Folder;
            }
        }

        public virtual void ItemAdded(ListMakerItem item)
        {
            _byteUsed += item.ByteSize;
            _timeUsed += item.Duration;
            _itemUsed++;
        }

        public virtual TimeSpan TimeCapacity
        {
            get {return _timeCap;}
        }

        public virtual long ByteCapacity
        {
            get {return _byteCap;}
        }

        public virtual void Cancel()
        {
            //This can happen before or after Launch
            _byteUsed = 0;
            _timeUsed = new TimeSpan(0, 0, 0);
            _itemUsed = 0;
            _progressPercentage = 0.0F;
            _timeRemaining = TimeSpan.Zero;
            _fCancel = true;
        }

        public bool Succeeded
        {
            get {return true;}
        }

        public Exception FailureReason
        {
            get {return null;}
        }
        #endregion
    }
}

